/*
 * @Author: Cenven
 * @Date: 2021-03-04 14:28:45
 * @Description: 北京泓深教育发展有限公司
 * @Descripttion:
 * @version: @Lastest
 * @LastEditTime: 2021-04-01 17:34:53
 * @CopyRight: 北京泓深教育发展有限公司
 */
import { mapState, mapActions, mapMutations } from "vuex";
import { getTrtcSign, getTrtcUserSign } from "~/api/chapter.js";

const originState = {
  is_join_channel: false, //是否加入了直播间
  is_camera_extended: false, //是否将摄像移动主面板
  is_show_controls: false, //是否显示操作面板
  is_mute_volume: false, //是否禁音
  is_full_screen: false, //视频全屏
  is_extend_subScreen: false, //主副屏切换
  is_share_screen: false, //共享流是否开启 (远程端)
  is_share_video: false, //视频流是否开启 (远程端)
  is_proccesing: false, //处理中
  is_subscribed_teacher: false, //是否订阅老师
  timeout: null, //防抖函数计时器
  timer: null, //全屏事件监听定时器
  /**
   * trtc_info
   */
  trtc: null,
  trtc_info: {
    isPublished_: false, //是否发布了本地流
    is_join: false, //是否已经加入直播间
    cameraId: "",
    micId: "",
    options: {
      sdkAppId: "",
      userId: "",
      userSig: "",
      roomId: ""
    }
  },
  remoteStreams_: [], //远程流
  remoteStreams_state: [], //远程流音视频状态
  localStream_: null, //本地流
  count_timer: null, //直播是否到达结束时间 计时器
  trtc_config: {
    sdkAppId: "",
    userSig: "",
    privateMapKey: ""
  }
};
export default {
  props: ["chapter_obj", "teacher_obj"],
  components: {},
  data() {
    return { ...originState };
  },
  computed: {
    ...mapState({
      user_info(state) {
        return state.user_info;
      },
      is_mobile(state) {
        return state.is_mobile;
      },
      token(state) {
        return state.token;
      },
      is_ios(state) {
        return state.is_ios;
      }
    }),
    userId() {
      if (this.user_info.mobile) {
        return this.user_info.mobile;
      } else if (this.user_info.id) {
        return this.user_info.id;
      }
    }
  },
  watch: {
    chapter_obj: {
      handler(a, b, c) {
        const video = this.$refs.rtcVideo;
        video &&
          video.removeEventListener(
            "webkitfullscreenchange",
            this.onFullscreenChange
          );
        video &&
          video.removeEventListener(
            "fullscreenchange",
            this.onFullscreenChange
          );
        this.initState();
        this.$nextTick(() => {
          this.startRTC();
        });
      },
      deep: true // 必须加这个属性
    }
  },
  activated() {
    this.$nextTick(() => {
      if (process.client) {
        this.startRTC();
        window.addEventListener("beforeunload", this.stopLive, false);
      }
    });
  },
  deactivated() {
    console.log("重载直播间");
    this.count_timer && clearInterval(this.count_timer);
    this.stopLive();
    this.initState();
    window.removeEventListener("beforeunload", this.stopLive);
  },
  destroyed() {
    console.log("离开直播间");
    this.count_timer && clearInterval(this.count_timer);
    this.stopLive();
    this.initState();
    window.removeEventListener("beforeunload", this.stopLive);
  },
  methods: {
    initState() {
      Object.assign(this.$data, originState);
    },
    /* 开始直播 */
    async startRTC() {
      let checkResult = await TRTC.checkSystemRequirements();
      console.log("checkResult:", checkResult);
      if (checkResult.result && checkResult.detail) {
        let { cameraId, micId } = this.trtc_info;
        TRTC.getDevices()
          .then(devices => {
            console.log("获取设备：", devices);
          })
          .catch(error => console.error("getDevices error observed " + error));

        TRTC.getCameras().then(devices => {
          console.log("获取摄像头：", devices);
          devices.forEach(device => {
            if (!cameraId) {
              this.trtc_info = {
                ...this.trtc_info,
                cameraId: device.deviceId
              };
            }
          });
        });

        // populate microphone options
        TRTC.getMicrophones().then(devices => {
          console.log("获取麦克风：", devices);
          devices.forEach(device => {
            if (!micId) {
              this.trtc_info = {
                ...this.trtc_info,
                micId: device.deviceId
              };
            }
          });
        });
        // TRTC.Logger.setLogLevel(TRTC.Logger.LogLevel.TRACE);
        this.initRTC();
      } else {
        this.$toast("当前环境不支持直播，请切换浏览器重试！");
      }
    },
    /* 初始化trtc */
    async initRTC() {
      let result = await this.getTrtcSign();
      let result1 = await this.getTrtcUserSign();
      if (result && result1) {
        let userId = this.userId;
        const { sdkAppId, userSig } = this.trtc_config;
        let options = {
          sdkAppId,
          userId,
          userSig,
          roomId: Number(this.chapter_obj.id)
        };
        this.trtc_info = {
          ...this.trtc_info,
          options
        };
        this.trtc = TRTC.createClient({
          mode: "rtc",
          sdkAppId: options.sdkAppId,
          userId: options.userId,
          userSig: options.userSig
        });
        this.handleEvents();
      } else {
        console.warn("获取鉴权失败！");
      }
    },
    removeView(userId) {
      this.remoteStreams_ = this.remoteStreams_.filter(stream => {
        return stream.userId_ !== userId;
      });
      if (this.remoteStreams_.length == 0) {
        this.stopLive();
      }
    },
    /* trtc事件 */
    handleEvents() {
      let __EVENTS__ = {
        error: evt => {
          console.warn("error:", evt);
        },
        "client-banned": evt => {
          console.warn("client-banned:", evt);
        },
        "peer-join": evt => {
          console.warn("peer-join:", evt);
        },
        "peer-leave": evt => {
          console.warn("peer-leave:", evt);
          const userId = evt.userId;
          this.removeView(userId);
        },
        "stream-added": evt => {
          console.warn("stream-added:", evt);
          const remoteStream = evt.stream;
          const id = remoteStream.getId();
          const userId = remoteStream.getUserId();
          console.log(
            `remote stream added: [${userId}] ID: ${id} type: ${remoteStream.getType()}`
          );
          /**
           * 仅订阅课程老师和管理员的流
           */
          if (
            /admin-/.test(userId) ||
            userId == this.teacher_obj.id ||
            userId == "share_" + this.teacher_obj.id
          ) {
            this.trtc.subscribe(remoteStream);
          } else {
            this.trtc.unsubscribe(remoteStream);
          }
        },
        "stream-subscribed": evt => {
          console.warn("stream-subscribed:", evt);
          const uid = evt.stream.userId_;
          const remoteStream = evt.stream;
          const userId = remoteStream.getUserId();
          const id = remoteStream.getId();
          if (
            this.remoteStreams_.filter(
              item => item.userId_ == remoteStream.userId_
            ).length > 0
          ) {
            console.warn("已存在该用户！", remoteStream.userId_);
            return;
          }
          if (remoteStream.userId_ == this.user_info.id) {
            console.warn("不订阅当前用户（自己）！", remoteStream.userId_);
            return;
          }
          if (remoteStream.userId_ == "share_" + this.user_info.id) {
            console.warn(
              "不订阅当前用户（自己）屏幕共享！",
              remoteStream.userId_
            );
            return;
          }
          if (
            !(
              /admin-/.test(userId) ||
              userId == this.teacher_obj.id ||
              userId == "share_" + this.teacher_obj.id
            )
          ) {
            console.warn(
              "不订阅除课程老师和管理员以外的人",
              remoteStream.userId_
            );
            return;
          }
          remoteStream.is_subscribe = true;
          this.remoteStreams_.push(remoteStream);
          remoteStream.on("player-state-changed", event => {
            console.log(`${event.type} player is ${event.state}`);
            if (event.state === "PAUSED") {
              remoteStream.resume();
            }
            if (event.type == "video" && event.state == "STOPPED") {
            }
            if (event.type == "video" && event.state == "PLAYING") {
            }
          });
          this.$nextTick(() => {
            /* 屏幕共享流 */
            if (
              remoteStream.userId_ &&
              remoteStream.userId_.indexOf("share_") > -1
            ) {
              let domId = "rtcShareVideo";
              remoteStream.play(domId, { objectFit: "contain" }).then(() => {
                // Firefox，当video的controls设置为true的时候，video-box无法监听到click事件
                // if (getBrowser().browser === 'Firefox') {
                //   return;
                // }
                // remoteStream.videoPlayer_.element_.controls = true;
              });
              remoteStream.on("error", error => {
                const errorCode = error.getCode();
                if (errorCode === 0x4043) {
                  // PLAY_NOT_ALLOWED,引导用户手势操作并调用 stream.resume 恢复音视频播放
                  remoteStream.resume();
                }
              });
              this.is_share_screen = true;
              this.is_subscribed_teacher = true;
              /* 视频共享流 */
            } else {
              let domId = "rtcVideo";
              remoteStream.play(domId).catch(error => {});
              remoteStream.on("error", error => {
                const errorCode = error.getCode();
                if (errorCode === 0x4043) {
                  // PLAY_NOT_ALLOWED,引导用户手势操作并调用 stream.resume 恢复音视频播放
                  remoteStream.resume();
                }
              });
              this.is_share_video = true;
              this.is_subscribed_teacher = true;
            }
          });
        },
        "stream-removed": evt => {
          console.warn("stream-removed:", evt);
          const remoteStream = evt.stream;
          const id = remoteStream.getId();
          remoteStream.stop();
          this.remoteStreams_ = this.remoteStreams_.filter(stream => {
            return stream.getId() !== id;
          });
        },
        "stream-updated": evt => {
          console.warn("stream-updated:", evt);
          this.updateRomateState();
        },
        "mute-audio": evt => {
          console.warn("mute-audio:", evt);
          this.updateRomateState();
        },
        "unmute-audio": evt => {
          console.warn("unmute-audio:", evt);
          this.updateRomateState();
        },
        "mute-video": evt => {
          console.warn("mute-video:", evt);
          this.updateRomateState();
        },
        "unmute-video": evt => {
          console.warn("unmute-video:", evt);
          this.updateRomateState();
        }
      };
      Object.keys(__EVENTS__).forEach(item => {
        console.warn("注册事件" + item + "成功");
        this.trtc.on(item, __EVENTS__[item]);
      });
    },
    /* 加入直播间 */
    async joinroom(callback) {
      let { is_join, cameraId, micId, isPublished_, options } = this.trtc_info;
      if (is_join) {
        this.$toast("已经加入直播间，不可重复加入");
      } else {
        const { liveEndTime, liveStartTime } = this.chapter_obj;
        let current_time = new Date().getTime();
        if (current_time < liveStartTime) {
          this.$toast("当前直播还没开始");
          return;
        } else if (current_time >= liveEndTime) {
          this.$toast("当前直播已经结束");
          return;
        }
        await this.trtc.join({
          roomId: options.roomId
        });
        this.trtc_info = {
          ...this.trtc_info,
          is_join: true
        };
        if (cameraId && micId) {
          this.localStream_ = TRTC.createStream({
            audio: true,
            video: true,
            userId: options.userId,
            cameraId: cameraId,
            microphoneId: micId,
            mirror: true
          });
        } else {
          this.localStream_ = TRTC.createStream({
            audio: true,
            video: true,
            userId: options.userId,
            mirror: true
          });
        }
        try {
          // initialize the local stream and the stream will be populated with audio/video
          await this.localStream_.initialize();
          console.log("initialize local stream success");

          this.localStream_.on("player-state-changed", event => {
            console.log(`local stream ${event.type} player is ${event.state}`);
          });
        } catch (e) {
          console.error("failed to initialize local stream - " + e);
          switch (e.name) {
            case "NotReadableError":
              this.$toast(
                "暂时无法访问摄像头/麦克风，请确保系统允许当前浏览器访问摄像头/麦克风，并且没有其他应用占用摄像头/麦克风"
              );
              return;
            case "NotAllowedError":
              if (e.message === "Permission denied by system") {
                this.$toast("请确保系统允许当前浏览器访问摄像头/麦克风");
              } else {
                console.log("User refused to share the screen");
              }
              return;
            case "NotFoundError":
              this.$toast(
                "浏览器获取不到摄像头/麦克风设备，请检查设备连接并且确保系统允许当前浏览器访问摄像头/麦克风"
              );
              return;
            default:
              return;
          }
        }

        try {
          if (!this.trtc_info.is_join) {
            console.warn("publish() - please join() firstly");
            return;
          }
          if (this.trtc_info.isPublished_) {
            console.warn("duplicate RtcClient.publish() observed");
            return;
          }
          try {
            await this.trtc.publish(this.localStream_);
          } catch (e) {
            console.error("failed to publish local stream " + e);
            this.trtc_info = {
              ...this.trtc_info,
              isPublished_: false
            };
          }
          this.trtc_info = {
            ...this.trtc_info,
            isPublished_: true
          };
          this.is_join_channel = true;
          this.count_timer = setInterval(this.startCounting, 5000);
        } catch (e) {
          console.error("failed to publish local stream - ", e);
        }
      }
    },
    /** 更新流状态 */
    async updateRomateState(arg) {
      let is_local_update = false,
        value = true,
        type = "";
      if (arg) {
        is_local_update = arg.is_local_update;
        value = arg.value;
        type = arg.type;
      }
      let state_list = await this.trtc.getRemoteMutedState();
      console.log("更新流状态：", state_list);
      let user_list = this.remoteStreams_state.map(i => i.userId);
      this.remoteStreams_state = state_list.map(i => {
        const { audioMuted, hasAudio, hasVideo, userId, videoMuted } = i;
        /** 如果流状态存在 */
        if (user_list.includes(i.userId)) {
          /** 流状态副本 */
          let old_state = this.remoteStreams_state.filter(
            item => item.userId == i.userId
          )[0];
          /** 存在is_local_update 更新is_open_video或is_open_audio值为value */
          if (is_local_update) {
            if (type == "video") {
              return {
                ...old_state,
                is_open_video: value
              };
            } else if (type == "audio") {
              return {
                ...old_state,
                is_open_audio: value
              };
            }
            /** 不存在is_local_update 更新is_open_video或is_open_audio值为副本 */
          } else {
            return {
              ...i,
              is_open_video: old_state.is_open_video,
              is_open_audio: old_state.is_open_audio
            };
          }
          /** 如果流状态不存在 初始化is_open_video，is_open_audio */
        } else {
          return {
            ...i,
            is_open_video: hasVideo && !videoMuted,
            is_open_audio: hasAudio && !audioMuted
          };
        }
      });
    },
    /** 离开直播间 */
    async leave({ type }) {
      /** 屏幕共享 */
      if (type == "share") {
        this.remoteStreams_.forEach((i, x) => {
          if (/share_/.test(i.userId_)) {
            this.$set(this.remoteStreams_[x], "is_subscribe", false);
            this.trtc.unsubscribe(i);
          }
        });
        this.is_share_screen = false;
      } else if (type == "rtc") {
        let {
          is_join,
          cameraId,
          micId,
          isPublished_,
          options
        } = this.trtc_info;
        if (!is_join) {
          console.warn("leave() - please join() firstly");
          return;
        }
        // ensure the local stream is unpublished before leaving.
        await this.trtc.unpublish(this.localStream_);
        this.trtc_info = {
          ...this.trtc_info,
          isPublished_: false
        };

        // leave the room
        await this.trtc.leave();

        this.localStream_.stop();
        this.localStream_.close();
        this.localStream_ = null;
        this.trtc_info = {
          ...this.trtc_info,
          is_join: false
        };
        this.is_show_controls = false;
        this.is_share_video = false;
        this.is_subscribed_teacher = false;
        this.is_join_channel = false;
      }
    },
    /* 退出直播 */
    stopLive() {
      this.leave({ type: "share" });
      this.leave({ type: "rtc" });
    },
    handleStatus(type) {
      if (type == "play") {
        this.joinroom();
      } else if (type == "pause") {
        this.stopLive();
      }
    },
    /** 更新流状态事件回调 */
    async toggleRemoteMedia(type) {
      this.remoteStreams_state.forEach(i => {
        const {
          hasVideo,
          hasAudio,
          videoMuted,
          audioMuted,
          is_open_video,
          is_open_audio,
          userId
        } = i;
        let romate_stream = this.remoteStreams_.filter(
          item => item.userId_ == userId
        );
        if (romate_stream.length > 0) {
          const stream = romate_stream[0];
          if (type == "audio") {
            if (is_open_audio) {
              console.warn("关闭音频");
              stream.muteAudio();
              this.updateRomateState({
                is_local_update: true,
                value: false,
                type: "audio"
              });
              this.is_mute_volume = true;
            } else {
              console.warn("开启音频");
              stream.unmuteAudio();
              this.updateRomateState({
                is_local_update: true,
                value: true,
                type: "audio"
              });
              this.is_mute_volume = false;
            }
          } else if (type == "camera") {
            if (is_open_video) {
              console.warn("关闭视频");
              stream.muteVideo();
              this.updateRomateState({
                is_local_update: true,
                value: false,
                type: "video"
              });
            } else {
              console.warn("开启视频");
              stream.unmuteVideo();
              this.updateRomateState({
                is_local_update: true,
                value: true,
                type: "video"
              });
            }
          }
        }
      });
    },
    /* 视频控制条事件 */
    handleShowControls() {
      if (this.is_subscribed_teacher == true) {
        this.is_show_controls = true;
        this.debounce(() => {
          this.is_show_controls = false;
        }, 5000);
      }
    },
    /* 视频全屏 */
    fullScreen(type) {
      let video = null;
      if (this.is_extend_subScreen) {
        video = document.querySelector("#rtcShareVideo video");
      } else {
        video = document.querySelector("#rtcVideo video");
      }
      console.log("+++++++++++video:", video);
      if (video && type == "requestfull") {
        //视频全屏
        if (video.requestFullscreen) {
          video.requestFullscreen();
        } else if (video.mozRequestFullScreen) {
          video.mozRequestFullScreen();
        } else if (video.webkitRequestFullScreen) {
          video.webkitRequestFullScreen();
        } else if (video.webkitEnterFullscreen) {
          // iOS进入全屏
          video.webkitEnterFullscreen();
        }
        if (this.is_ios) {
          this.onFullscreenChange();
        } else {
          video.addEventListener(
            "webkitfullscreenchange",
            this.onFullscreenChange,
            false
          );
          video.addEventListener(
            "fullscreenchange",
            this.onFullscreenChange,
            false
          );
        }
        this.is_full_screen = true;
      } else if (video && type == "exitfull") {
        // //退出浏览器全屏
        // if (document.exitFullscreen) {
        //   document.exitFullscreen();
        // } else if (document.msExitFullscreen) {
        //   document.msExitFullscreen();
        // } else if (document.mozCancelFullScreen) {
        //   document.mozCancelFullScreen();
        // } else if (document.webkitExitFullscreen) {
        //   document.webkitExitFullscreen();
        // }
        //退出视频全屏
        if (video.exitFullscreen) {
          video.exitFullscreen();
        } else if (video.mozCancelFullScreen) {
          video.mozCancelFullScreen();
        } else if (video.webkitCancelFullScreen) {
          video.webkitCancelFullScreen();
        }
        this.is_full_screen = false;
      }
    },
    /* 退出视频全屏 */
    onFullscreenChange(e) {
      console.log("监听视频全屏：", e);
      const video = document.querySelector("#rtcVideo video");
      if (this.is_ios) {
        // 针对iOS监听不到webkitfullscreenchange事件做的兼容，感知退出全屏
        this.timer = setInterval(() => {
          if (!video.webkitDisplayingFullscreen) {
            // 退出了全屏
            clearInterval(this.timer);
            this.is_full_screen = false;
            video.play();
            video.removeEventListener(
              "webkitfullscreenchange",
              this.onFullscreenChange
            );
            video.removeEventListener(
              "fullscreenchange",
              this.onFullscreenChange
            );
          }
        }, 1000);
      } else {
        if (!video.webkitDisplayingFullscreen) {
          // 退出全屏
          this.is_full_screen = false;
          video.removeEventListener(
            "webkitfullscreenchange",
            this.onFullscreenChange
          );
          video.removeEventListener(
            "fullscreenchange",
            this.onFullscreenChange
          );
        }
      }
    },
    //防抖
    debounce(func, wait) {
      const _this = this;
      return !(function() {
        let context = this;
        let args = arguments;

        if (_this.timeout) clearTimeout(_this.timeout);

        _this.timeout = setTimeout(() => {
          func.apply(context, args);
        }, wait);
      })();
    },
    //屏幕交换
    exchangeScreen() {
      this.is_extend_subScreen = !this.is_extend_subScreen;
    },
    /* 监听直播是否已经到达开播结束事件 */
    startCounting() {
      let current_time = new Date().getTime();
      const { liveEndTime } = this.chapter_obj;
      if (current_time >= liveEndTime) {
        this.stopLive();
        this.$toast("当前直播已结束！");
        this.count_timer && clearInterval(this.count_timer);
      }
    },
    /* 获取 PrivateMapKey 权限票据*/
    async getTrtcSign() {
      return new Promise(async (res, rej) => {
        let userId = this.userId;
        let params = {
          userId,
          roomId: String(this.chapter_obj.id),
          type: 2,
          privilegeMap: 11111111
        };
        let result = await getTrtcSign(params);
        console.log("获取 PrivateMapKey:", result);
        if (result && result.data && result.data.code == 200) {
          const { data } = result.data;
          this.trtc_config = {
            ...data
          };
          res(data);
        } else {
          rej(false);
        }
      }).then();
    },
    /*  UserSig 鉴权票据 */
    async getTrtcUserSign() {
      return new Promise(async (res, rej) => {
        let userId = this.userId;
        let params = {
          userId,
          type: 2
        };
        let result = await getTrtcUserSign(params);
        console.log("获取 UserSig:", result);
        if (result && result.data && result.data.code == 200) {
          const { data } = result.data;
          this.trtc_config = {
            ...data
          };
          res(data);
        } else {
          rej(false);
        }
      }).then();
    }
  },
  created() {
    this.$nextTick(() => {
      if (process.client) {
        this.startRTC();
        window.addEventListener("beforeunload", this.stopLive, false);
      }
    });
  },
  mounted() {}
};
